package com.ctshk.app.user.controller;

import cn.hutool.core.util.RandomUtil;
import com.ctshk.common.annotations.OperationLogAnnotation;
import com.ctshk.common.constant.CurrencyRateExchangeConstant;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.*;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.rpc.starvip.dto.UserMemberBasicInformationDTO;
import com.ctshk.rpc.starvip.dto.start_vip.transaction.LoyTransactionQuery;
import com.ctshk.rpc.starvip.dto.start_vip.transaction.TrainIntegralDTO;
import com.ctshk.rpc.starvip.dto.start_vip.transaction.TransactionQueryDTO;
import com.ctshk.rpc.starvip.dto.start_vip.user.Contact;
import com.ctshk.rpc.starvip.dto.start_vip.user.LoyMember;
import com.ctshk.rpc.starvip.enums.transaction.StarVipTransactionType;
import com.ctshk.rpc.starvip.req.TransactionIntegralReq;
import com.ctshk.rpc.starvip.req.UserMemberBasicInformationReq;
import com.ctshk.rpc.starvip.req.transaction.StarVipTransactionIntegralReq;
import com.ctshk.rpc.starvip.req.transaction.StarVipTransactionQueryReq;
import com.ctshk.rpc.starvip.req.user.UserInfoQueryReq;
import com.ctshk.rpc.starvip.service.IStarVipBusinessService;
import com.ctshk.rpc.starvip.service.IStarVipMemberService;
import com.ctshk.rpc.starvip.service.IStarVipTransactionService;
import com.ctshk.rpc.starvip.service.IStarVipUserService;import com.ctshk.rpc.system.service.IMainDataCurrencyService;
import com.ctshk.rpc.user.dto.AvailableIntegralDTO;
import com.ctshk.rpc.user.dto.IntegralDTO;
import com.ctshk.rpc.user.dto.UserTransactionQueryDTO;
import com.ctshk.rpc.user.dto.AppUserDTO;
import com.ctshk.rpc.user.req.IntegralReq;
import com.ctshk.rpc.user.req.TransactionQueryReq;
import com.ctshk.rpc.user.req.UserTransactionReq;
import com.ctshk.rpc.user.service.IUserService;
import com.ctshk.rpc.user.service.IUserStarVipService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 *  我的積分前端控制器
 * </p>
 *
 * @author 李新科
 * @date 2021/5/18 20:42
 */
@Api(value="我的積分", tags="我的積分")
@RestController
@RequestMapping("/vip")
public class StarVipController extends AppBaseController {

    @DubboReference
    private IStarVipBusinessService starVipBusinessService;

    @DubboReference
    private IStarVipMemberService starVipMemberService;

    @DubboReference
    private IStarVipUserService starVipUserService;

    @DubboReference
    private IUserService userService;

    @DubboReference
    private IStarVipTransactionService transactionService;

    @DubboReference
    private IUserStarVipService userStarVipService;

    @DubboReference
    private IMainDataCurrencyService mainDataCurrencyService;

    @ApiOperation(value="个人中心-我的积分", notes="个人中心-我的积分")
    @OperationLogAnnotation(operModul = OperationLogModel.USER, operType = OperationLogType.QUERY, operTitle = "个人中心-我的积分", operDesc = "个人中心-我的积分")
    @PostMapping("/availableIntegral")
    public Result<AvailableIntegralDTO> availableIntegral() throws Exception{

        TokenUser currentUser = getCurrentUser();
        AppUserDTO userDTO = userService.queryCacheUser(currentUser.getId());
        if(userDTO.getIsInternalMember() == 1) {
            UserMemberBasicInformationReq userMemberBasicInformationReq = new UserMemberBasicInformationReq();
            userMemberBasicInformationReq.setCtsLogin(userDTO.getUserAccount());
            AvailableIntegralDTO availableIntegralDTO = new AvailableIntegralDTO();
            try {
                Result<UserMemberBasicInformationDTO> userMemberBasicInformation = starVipBusinessService.getUserMemberBasicInformation(userMemberBasicInformationReq);
                if(userMemberBasicInformation.isSuccess()) {
                    UserMemberBasicInformationDTO data = userMemberBasicInformation.getData();
                    Long point = Long.valueOf(data.getPoint1Value());
                    availableIntegralDTO.setAvailable(point);
                    availableIntegralDTO.setDeduction(new BigDecimal(point / 100.0));
                    availableIntegralDTO.setExpectedToExpirePoint(BigDecimal.ZERO.longValue());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return Result.success(availableIntegralDTO);
        } else {
            return Result.failed(new BusinessException(SystemError.STAR_VIP_20004));
        }
    }

    @ApiOperation(value="積分記錄", notes="積分記錄")
    @OperationLogAnnotation(operModul = OperationLogModel.USER, operType = OperationLogType.QUERY, operTitle = "積分記錄", operDesc = "積分記錄")
    @PostMapping("/list")
    public Result<PageResponse<UserTransactionQueryDTO>> queryPage(@RequestBody TransactionQueryReq req) throws Exception{
        TokenUser currentUser = getCurrentUser();
        AppUserDTO userDTO = userService.queryCacheUser(currentUser.getId());
        //List<TransactionQueryDTO> list = mockTransactionQueryDTO(req);

        if(userDTO.getIsInternalMember() == 1) {
            List<UserTransactionQueryDTO> list = new ArrayList<>();
            StarVipTransactionQueryReq starVipTransactionQueryReq = new StarVipTransactionQueryReq();
            starVipTransactionQueryReq.setMemberId(userDTO.getMemberId());
            LocalDateTime now = LocalDateTime.now();
            starVipTransactionQueryReq.setTransactionBeginDate(now.minusYears(1));
            starVipTransactionQueryReq.setTransactionEndDate(now);
            String transactionType = null;
            Integer reqType = req.getType();
            if(reqType != null) {
                if(reqType == 1) {
                    transactionType = StarVipTransactionType.ACCRUAL.getName();
                } else if(reqType == 2) {
                    transactionType = StarVipTransactionType.REDEMPTION.getName();
                }
            }
            starVipTransactionQueryReq.setTransactionType(transactionType);
            starVipTransactionQueryReq.setPageNo(req.getPageNo());
            starVipTransactionQueryReq.setPageSize(req.getPageSize());

            Result<TransactionQueryDTO> transactionQueryDTOResult = transactionService.queryTransaction(starVipTransactionQueryReq);
            int total = 0;
            if(transactionQueryDTOResult.isSuccess()) {
                TransactionQueryDTO data = transactionQueryDTOResult.getData();
                List<LoyTransactionQuery> loyTransaction = data.getListOfCtsLoyTransactionQuery().getLoyTransaction();
                if(!CollectionUtils.isEmpty(loyTransaction)) {
                    for (LoyTransactionQuery loyTransactionQuery : loyTransaction) {
                        UserTransactionQueryDTO userTransactionQueryDTO = new UserTransactionQueryDTO();
                        userTransactionQueryDTO.setTitle(loyTransactionQuery.getProductName());
                        userTransactionQueryDTO.setDate(loyTransactionQuery.getTransactionDate());
                        userTransactionQueryDTO.setPoint(loyTransactionQuery.getPoints());
                        Integer type = null;
                        if(StarVipTransactionType.ACCRUAL.getCode().equals(loyTransactionQuery.getTransactionType())) {
                            type = 1;
                        } else if(StarVipTransactionType.REDEMPTION.getCode().equals(loyTransactionQuery.getTransactionType())) {
                            type = 2;
                        }
                        userTransactionQueryDTO.setType(type);
                        LocalDateTime expirationDate = loyTransactionQuery.getExpirationDate();
                        if(expirationDate != null) {
                            if(now.isBefore(expirationDate)) {
                                userTransactionQueryDTO.setExpireDayNum(Duration.between(now,expirationDate).toDays());
                            }
                        }

                        list.add(userTransactionQueryDTO);
                    }

                }
                String txnNumber = data.getTxnNumber();
                if(StringUtils.isNotBlank(txnNumber)) {
                    total = Integer.valueOf(txnNumber);
                }

            }
            PageResponse<UserTransactionQueryDTO> response = new PageResponse<UserTransactionQueryDTO>(list, true, true, list.size(), req.getPageNo(), req.getPageSize());
            return Result.success(response);
        } else {
            return Result.failed(new BusinessException(SystemError.STAR_VIP_20004));
        }
    }

    /**
     * 生成随机数据
     * @param req
     * @return
     */
    private List<UserTransactionQueryDTO> mockTransactionQueryDTO(TransactionQueryReq req) {
        int num = RandomUtil.randomInt(1,10);
        List<UserTransactionQueryDTO> result = new ArrayList<>(num);
        LocalDateTime now = LocalDateTime.now();
        for (int i = 0; i < num; i++) {
            UserTransactionQueryDTO transactionQueryDTO = new UserTransactionQueryDTO();
            transactionQueryDTO.setTitle("预订" + SystemBusinessType.parseValue(RandomUtil.randomInt(1,19)));
            transactionQueryDTO.setDate(now.minusDays(i));
            transactionQueryDTO.setPoint(BigDecimal.valueOf(RandomUtil.randomInt(1,10) * 10));
            if(req.getType() != null) {
                transactionQueryDTO.setType(req.getType());
            } else {
                transactionQueryDTO.setType(RandomUtil.randomInt(1,3));
            }

            if(transactionQueryDTO.getType() == 1) {
                transactionQueryDTO.setExpireDayNum(Long.valueOf(RandomUtil.randomInt(1,41)));
            }

            result.add(transactionQueryDTO);
        }

        return result;
    }

    @ApiOperation(value="测试xml星赏会会员", notes="测试xml星赏会会员")
    @OperationLogAnnotation(operModul = OperationLogModel.USER, operType = OperationLogType.QUERY, operTitle = "测试xml星赏会会员", operDesc = "测试xml星赏会会员")
    @PostMapping("/testXml")
    public String testXml(@RequestBody String xml) throws Exception{
        return starVipUserService.testXml(xml);
    }

    @ApiOperation(value="C端填写订单查询可获积分和抵扣金额", notes="會員积分,当前可用积分,积分抵扣金额,金额可获得积分")
    @OperationLogAnnotation(operModul = OperationLogModel.USER, operType = OperationLogType.QUERY, operTitle = "會員积分", operDesc = "會員积分")
    @PostMapping("/integral")
    public Result<IntegralDTO> integral(@RequestBody @Valid IntegralReq req) throws Exception{
        Long userId = getCurrentUserAllowNotLogInUserId();
        String memberId = null;
        if(userId != null) {
            AppUserDTO userDTO = userService.queryCacheUser(userId);
            if(userDTO != null) {
                memberId = userDTO.getMemberId();
            }
        }
        BigDecimal exchangeRate = mainDataCurrencyService.getExchangeRate(String.valueOf(Currency.CNY.getCurrency()), CurrencyRateExchangeConstant.CRM_EXCHANGE_RATE_);
        TrainIntegralDTO trainIntegralDTO = starVipBusinessService.queryIntegralAndHkd(new StarVipTransactionIntegralReq()
                .setMemberId(memberId)
                .setBusinessType(req.getType())
                .setReceivableAmount(req.getPrice())
                .setExchangeRate(exchangeRate)
        );
        IntegralDTO integralDTO = EntityUtil.copy(trainIntegralDTO, IntegralDTO.class);
        return Result.success(integralDTO);
    }

    @ApiOperation(value="测试积分交易", notes="测试积分交易")
    @OperationLogAnnotation(operModul = OperationLogModel.USER, operType = OperationLogType.QUERY, operTitle = "测试积分交易", operDesc = "测试积分交易")
    @PostMapping("/transactionIntegral")
    public Result transactionIntegral(@RequestBody @Valid UserTransactionReq req) throws Exception{
        UserInfoQueryReq userInfoQueryReq = new UserInfoQueryReq();
        userInfoQueryReq.setCellularPhone(req.getContactMobileAreaCode() + "-" + req.getContactNumber());
        Result<Contact> contactResult = starVipUserService.userInfoQuery(userInfoQueryReq);
        if(contactResult.isSuccess()) {
            Contact contact = contactResult.getData();
            LoyMember loyMember = contact.getListOfLoyMember().getLoyMember().get(0);
            TransactionIntegralReq transactionIntegralReq = new TransactionIntegralReq();
            transactionIntegralReq.setCtsLogin(loyMember.getCtsLogin());
            transactionIntegralReq.setCtsPassword(loyMember.getCtsPassword());
            transactionIntegralReq.setPoints(req.getPoints());
            transactionIntegralReq.setOrderNumber(String.valueOf(System.currentTimeMillis()));
            transactionIntegralReq.setTransactionType(String.valueOf(req.getTransactionType()));
            starVipBusinessService.transactionIntegralThree(transactionIntegralReq);
            return Result.success();
        }

        return Result.failed(new BusinessException(SystemError.SYS_433,"交易失败"));

    }

    @ApiOperation(value="测试订单完成7天后增加积分和升级会员", notes="测试订单完成7天后增加积分和升级会员")
    @PostMapping("/testAddPoint")
    public Result testAddPoint(String jobParams) throws Exception{
        return userStarVipService.addPoints(jobParams);
    }

    @ApiOperation(value="测试根据会员Id查询积分兑换港币", notes="测试根据会员Id查询积分兑换港币")
    @PostMapping("/testGetHkd")
    public BigDecimal testXml(String memberId,BigDecimal receivableAmount) throws Exception{
        return starVipBusinessService.getHkd(memberId,receivableAmount);
    }

    /**
     * 根据业务类型,会员等级判断该金额可获得多少积分
     * @param type 业务类型
     * @param memberTierCode 会员等级代码
     * @param price   金额
     * @return
     */
    private Long getObtainByType(Integer type,String memberTierCode,BigDecimal price) {
        Long obtain = 0L;
        BigDecimal deduction = BigDecimal.ZERO;
        boolean numeric = StringUtils.isNumeric(memberTierCode);
        Integer level = 0;
        if(numeric) {
            level = Integer.valueOf(memberTierCode);
        }

        if(SystemBusinessType.OUTBOUND_TRAVEL.getCode() == type || SystemBusinessType.INBOUND_TRAVEL.getCode() == type) {
            if(level > 0 && level < 3) {
                obtain = price.divide(new BigDecimal(3),0,BigDecimal.ROUND_DOWN).longValue();
            } else if(level > 2 && level < 5) {
                obtain = price.divide(new BigDecimal(2),0,BigDecimal.ROUND_DOWN).longValue();
            }
        } else if (SystemBusinessType.FIXED_PACKAGE_TICKET.getCode() == type || SystemBusinessType.DYNAMIC_PACKAGE_TICKET.getCode() == type) {
            if(level > 0 && level < 3) {
                obtain = price.divide(new BigDecimal(3),0,BigDecimal.ROUND_DOWN).longValue();
            } else if(level > 2 && level < 5) {
                obtain = price.divide(new BigDecimal(2),0,BigDecimal.ROUND_DOWN).longValue();
            }
        }  else if (SystemBusinessType.HOTEL.getCode() == type) {
            if(level > 0 && level < 3) {
                obtain = price.divide(new BigDecimal(10),0,BigDecimal.ROUND_DOWN).longValue();
            } else if(level > 2 && level < 5) {
                obtain = price.divide(new BigDecimal(5),0,BigDecimal.ROUND_DOWN).longValue();
            }
        } else if (SystemBusinessType.ATTRACTION_TICKET.getCode() == type) {
            if(level > 0 && level < 3) {
                obtain = price.divide(new BigDecimal(20),0,BigDecimal.ROUND_DOWN).longValue();
            } else if(level > 2 && level < 5) {
                obtain = price.divide(new BigDecimal(10),0,BigDecimal.ROUND_DOWN).longValue();
            }
        } else if (SystemBusinessType.AIR_TICKET.getCode() == type
                || SystemBusinessType.SHIP_TICKET.getCode() == type
                || SystemBusinessType.TRAIN_TICKET.getCode() == type
                || SystemBusinessType.AIR_EXPRESS.getCode() == type
                || SystemBusinessType.BUS_TICKET.getCode() == type) {
            if(level > 0 && level < 3) {
                obtain = price.divide(new BigDecimal(30),0,BigDecimal.ROUND_DOWN).longValue();
            } else if(level > 2 && level < 5) {
                obtain = price.divide(new BigDecimal(20),0,BigDecimal.ROUND_DOWN).longValue();
            }
        }

        return obtain;
    }
}
